home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1985-1992 New York University
- *
- * This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
- * warranty (none) and distribution info and also the GNU General Public
- * License for more details.
-
- */
-
- #include "hdr.h"
- #include "libhdr.h"
- #include "vars.h"
- #include "setprots.h"
- #include "dclmapprots.h"
- #include "errmsgprots.h"
- #include "miscprots.h"
- #include "smiscprots.h"
- #include "nodesprots.h"
- #include "utilprots.h"
- #include "chapprots.h"
- #include "libprots.h"
-
- static void invisible_designator(Node, char *);
- static Tuple derived_formals(Symbol, Tuple);
- static void proc_or_entry(Node);
- static void new_over_spec(Symbol, int, Symbol, Tuple, Symbol, Node);
-
- void subprog_decl(Node node) /*;subprog_decl*/
- {
- Node spec_node, id_node, neq_node, eq_node;
- Symbol subp_name, neq;
- int exists;
- Forset fs1;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : subprog_decl");
-
- spec_node = N_AST1(node);
- id_node = N_AST1(spec_node);
- new_compunit("ss", id_node);
- adasem(spec_node);
- check_spec(node);
-
- subp_name = N_UNQ(id_node);
- save_subprog_info(subp_name);
-
- /* Modify the node kind for subprogram declarations to be
- * as_subprogram_decl_tr so that their specification part need not be
- * saved in the tree automatically. The formal part will be saved by
- * collect_unit_nodes only in the case of a subprogram specification
- * that is not in the same unit as the body as it is then needed for
- * conformance checks. In addition the node as_procedure (as_function)
- * is no longer needed in the tree since this info is obtained from
- * the symbol table.
- * Since the spec part is now dropped we now move the id_node info
- * (name of the subprogram) to the N_UNQ filed of the as_subprogram_decl_tr
- * node directly.
- */
-
- N_KIND(node) = as_subprogram_decl_tr;
- N_UNQ(node) = N_UNQ(id_node);
- if (streq(N_VAL(id_node) , "=") && tup_size(SIGNATURE(subp_name)) == 2) {
- /* build tree for declaration of inequality that was just introduced
- * (in the current scope, or the enclosing one, if now in private part).
- */
- exists = FALSE;
- FORSET(neq = (Symbol), OVERLOADS(dcl_get(DECLARED(SCOPE_OF(subp_name)),
- "/=")), fs1);
- if ( same_signature(neq, subp_name) ) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (exists) {
- neq_node = copy_tree(node); /* a valid subprogram decl*/
- N_UNQ(neq_node) = neq;
- eq_node = copy_node(node);
- make_insert_node(node, tup_new1((char *) eq_node), neq_node);
- }
- }
- }
-
- void check_spec(Node node) /*;check_spec*/
- {
- /* If the subprogram name is an operator designator, verify that it has
- * the proper type and number of arguments.
- */
-
- int proc_nat;
- Node spec_node, id_node, formal_node, ret_node;
- char *proc_id;
- Tuple formals;
- Symbol ret;
- Symbol prog_name;
- int spec_kind, node_kind;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : check_spec ");
-
- spec_node = N_AST1(node);
- id_node = N_AST1(spec_node);
- formal_node = N_AST2(spec_node);
- ret_node = N_AST3(spec_node);
- proc_id = N_VAL(id_node);
-
- spec_kind = N_KIND(spec_node);
- if (spec_kind == as_procedure)
- ret = symbol_none;
- else
- ret = N_UNQ(ret_node);
-
- switch (node_kind = N_KIND(node)) {
- case as_subprogram_decl:
- if (spec_kind == as_procedure)
- proc_nat = na_procedure_spec;
- else
- proc_nat = na_function_spec;
- break;
- case as_subprogram:
- case as_subprogram_stub:
- case as_generic_subp:
- if (spec_kind == as_procedure)
- proc_nat = na_procedure;
- else
- proc_nat = na_function;
- break;
- }
-
- formals = get_formals(formal_node, proc_id);
-
- check_out_parameters(formals);
-
- if (in_op_designators(proc_id ))
- check_new_op(id_node, formals, ret);
-
- prog_name = chain_overloads(proc_id, proc_nat, ret, formals, (Symbol)0,
- formal_node);
- N_UNQ(id_node) = prog_name;
- }
-
- void check_new_op(Node id_node, Tuple formals, Symbol ret) /*;check_new_op */
- {
- /* apply special checks for definition of operators */
- char *proc_id;
- Tuple tup;
- Fortup ft1;
- Node initv;
- int exists;
- Symbol typ1;
-
- proc_id = N_VAL(id_node);
-
- if ((strcmp(proc_id , "+") == 0 || strcmp(proc_id, "-") == 0)
- && tup_size(formals) == 1)
- ; /* Unary operators.*/
- else if ( (strcmp(proc_id , "not") == 0 || strcmp(proc_id, "abs") == 0)
- ? tup_size(formals) == 1 : tup_size(formals) == 2 )
- ;
- else {
- #ifdef ERRNUM
- str_errmsgn(373, proc_id, 54, id_node);
- #else
- errmsg_str("Incorrect no. of arguments for operator %" , proc_id,
- "6.7", id_node);
- #endif
- }
-
- exists = FALSE;
- FORTUP(tup = (Tuple), formals, ft1);
- initv = (Node)tup[4];
- if (initv != OPT_NODE) {
- exists = TRUE;
- break;
- }
- ENDFORTUP(ft1);
- if (exists) {
- #ifdef ERRNUM
- errmsgn(53, 54, initv);
- #else
- errmsg("Initializations not allowed for operators", "6.7", initv);
- #endif
- }
- /* Apply the special checks on redefinitions of equality.*/
- else if (streq(proc_id , "=")) {
- typ1 = (Symbol) ((Tuple)formals[1])[3]; /* type of formal*/
- if (tup_size(formals) != 2
- || typ1 != (Symbol) ((Tuple)formals[2])[3]
- || ret != symbol_boolean) {
- #ifdef ERRNUM
- errmsgn(374, 54, id_node);
- #else
- errmsg("Invalid argument profile for \"=\"", "6.7", id_node);
- #endif
- }
- }
- else if (strcmp(proc_id , "/=") == 0) {
- #ifdef ERRNUM
- errmsgn(375, 54, id_node);
- #else
- errmsg(" /= cannot be given an explicit definition", "6.7", id_node);
- #endif
- }
- } /* end check_new_op */
-
- Tuple get_formals(Node formal_list, char *proc_id) /*;get_formals*/
- {
- /* Utility to format the formals of a subprogram specification, in the
- * internal form kept in the subprogram's signature.
- */
-
- Node formal_node, id_list, m_node, type_node, exp_node, id_node;
- Tuple formals, tup;
- Fortup ft1, ft2;
- int formal_index, f_mode;
- Symbol type_mark;
-
- formal_index = 0;
- FORTUP(formal_node = (Node), N_LIST(formal_list), ft1);
- id_list = N_AST1(formal_node);
- FORTUP(id_node = (Node), N_LIST(id_list), ft2);
- formal_index++;
- ENDFORTUP(ft2);
- ENDFORTUP(ft1);
- formals = tup_new(formal_index);
- formal_index = 0;
-
- FORTUP(formal_node = (Node), N_LIST(formal_list), ft1);
- id_list = N_AST1(formal_node);
- m_node = N_AST2(formal_node);
- type_node = N_AST3(formal_node);
- invisible_designator(type_node, proc_id);
- exp_node = N_AST4(formal_node);
- invisible_designator(exp_node, proc_id);
- f_mode = (int) N_VAL(m_node);
- if (f_mode == 0) f_mode = na_in; /* note using 0 for '' f_mode case */
- type_mark = find_type(copy_tree(type_node)); /* for conformance check */
- FORTUP(id_node = (Node), N_LIST(id_list), ft2);
- formal_index++;
- tup = tup_new(4);
- tup[1] = (char *)N_VAL(id_node);
- tup[2] = (char *) f_mode;
- tup[3] = (char *) type_mark;
- tup[4] = (char *) copy_tree(exp_node);
- formals[formal_index] = (char *) tup;
- ENDFORTUP(ft2);
- ENDFORTUP(ft1);
-
- return (formals);
- }
-
- static void invisible_designator(Node tree_node, char *proc_id)
- /*;invisible_designator*/
- {
- /*
- * check for premature use of formals
- */
-
- int nk;
- Node n;
- Fortup ft1;
-
- /* The designator of a subprogram is not visible within its specification.*/
-
- nk = N_KIND(tree_node);
- if (N_KIND(tree_node) == as_simple_name) {
- if (streq(N_VAL(tree_node), proc_id))
- #ifdef ERRNUM
- str_errmsgn(425, proc_id, 50, tree_node);
- #else
- errmsg_str("premature usage of %", proc_id, "8.3(16)", tree_node);
- #endif
- }
- else {
- if (N_AST1_DEFINED(nk)) invisible_designator(N_AST1(tree_node),proc_id);
- if (N_AST2_DEFINED(nk)) invisible_designator(N_AST2(tree_node),proc_id);
- if (N_AST3_DEFINED(nk)) invisible_designator(N_AST3(tree_node),proc_id);
- if (N_AST4_DEFINED(nk)) invisible_designator(N_AST4(tree_node),proc_id);
-
- if (N_LIST_DEFINED(nk) && N_LIST(tree_node) != (Tuple)0) {
- FORTUP(n = (Node), N_LIST(tree_node), ft1);
- invisible_designator(n, proc_id);
- ENDFORTUP(ft1);
- }
- }
- }
-
- void subprog_body(Node node) /*;subprog_body*/
- {
- Node specs_node, id_node, stats_node;
- Node eq_node, neq_node;
- char *spec_name, *prog_id;
- Symbol unname, prog_name, neq, scope;
- int i;
- Forset fs1;
- Fortup ft1;
- int exists;
- Tuple decscopes, decmaps, s_info;
- /* s_info may not be needed ds 30 jul*/
- Unitdecl ud;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : subprog_body");
-
- specs_node = N_AST1(node);
-
- id_node = N_AST1(specs_node);
- adasem(id_node);
- prog_id = N_VAL(id_node);
-
- if (IS_COMP_UNIT) {
- new_compunit("su", id_node);
- /* If the specification of the unit was itself a compilation unit, we
- * will verify that the two specs are conforming. If this is the
- * body to a generic comp. unit, will have to access and update the
- * spec. In both cases see if the spec. is available.
- */
- spec_name = strjoin("ss", prog_id); /* Already retrieved*/
- ud = unit_decl_get(spec_name);
- if (ud != (Unitdecl)0) {
- /* Unpack declarations and install symbol table of unit.
- * [unname, s_info, decmap] := UNIT_DECL(spec_name);
- */
- unname = ud->ud_unam;
- s_info = ud->ud_symbols;
- decscopes = ud->ud_decscopes;
- decmaps = ud->ud_decmaps;
- /* Must look before putting because name could have been 'with'ed */
- if (dcl_get(DECLARED(symbol_standard0), prog_id) != unname)
- dcl_put(DECLARED(symbol_standard0), prog_id, unname);
-
- /* (for decls = decmap(scope)) declared(scope) := decls; end; */
- FORTUPI(scope = (Symbol), decscopes, i, ft1);
- if (decmaps[i] != (char *)0)
- DECLARED(scope) = dcl_copy((Declaredmap) decmaps[i]);
- ENDFORTUP(ft1);
-
- /* TBSL does s_info need to be retored ?? */
- symtab_restore(s_info);
- }
- }
- check_old(id_node);
- prog_name = N_UNQ(id_node);
- if (prog_name != (Symbol)0
- &&(NATURE(prog_name) == na_generic_procedure_spec
- || NATURE(prog_name) == na_generic_function_spec)) {
- generic_subprog_body(prog_name, node);
- return;
- }
- else {
- /* (Re)process subprogram specification.*/
- adasem(specs_node);
- check_spec(node);
- prog_name = N_UNQ(id_node);
- if (NATURE(prog_name) !=na_procedure && NATURE(prog_name) !=na_function)
- /* illegal subprogram name or redeclaration */
- return;
-
- if (IS_COMP_UNIT && ud != (Unitdecl)0 && prog_name != unname) {
- /* Spec. does not match its previous occurrence, or several
- * subprograms with same name are present.
- */
- #ifdef ERRNUM
- errmsgn(376, 377, id_node);
- #else
- errmsg("library subprograms cannot be overloaded",
- "10.1(10)", id_node);
- #endif
- return;
- }
- }
- if (!streq(original_name(prog_name), unit_name_name(unit_name))) {
- /*
- * All types in the current declarative part must be forced before
- * entering a nested scope.
- */
- force_all_types();
- }
- newscope(prog_name);
- process_subprog_body(node, prog_name);
- force_all_types();
- popscope();
- save_subprog_info(prog_name);
- /* Modify the node kind for subprogram bodies to be as_subprogram_tr
- * so that their specfication part need not be saved in the tree
- * automatically. The formal part need not be saved for the bodies
- * since all the info is in the symbol table and the conformance checks
- * are done against the formal part saved for the specification if any
- * was given.
- * In addition the node as_procedure (as_function) is no longer needed
- * in the tree since this info is obtained from the symbol table.
- * Since the spec part is now dropped we now move the id_node info
- * (name of the subprogram) to the N_UNQ filed of the as_subprogram_tr
- * node directly. In order to put the unique name info in the
- * as_subprogram_tr node we must shift the stats_node (statement part)
- * from being N_AST3 to N_AST1 so that we can use the N_UNQ field.
- */
- N_KIND(node) = as_subprogram_tr;
- stats_node = N_AST3(node);
- N_AST1(node) = stats_node;
- N_UNQ(node) = N_UNQ(id_node);
-
- if (streq(prog_id , "=")) {
- exists = FALSE;
- FORSET(neq = (Symbol), OVERLOADS(dcl_get(DECLARED(SCOPE_OF(prog_name))
- , "/=")), fs1);
- if (same_signature(neq, prog_name) ) {
- exists = TRUE;
- break;
- }
- ENDFORSET(fs1);
- if (exists) {
- /* create body of corresponding inequality, whose implicit spec.
- * was introduced with the spec. of equality.
- */
- neq_node = new_not_equals(neq, prog_name);
- eq_node = copy_node(node);
- make_insert_node(node, tup_new1((char *) eq_node), neq_node);
- }
- }
- }
-
- void process_subprog_body(Node node, Symbol prog_name) /*;process_subprog_body*/
- {
- Node decl_node, stats_node, handler_node;
- int has_return;
-
- has_return_stk = tup_with(has_return_stk, (char *)FALSE);
-
- decl_node = N_AST2(node);
- stats_node = N_AST3(node);
- handler_node = N_AST4(node);
-
- lab_init();
- adasem(decl_node);
- adasem(stats_node);
- adasem(handler_node);
- lab_end(); /* Validate goto statements in subprogram*/
-
- has_return = (int) tup_frome(has_return_stk);
-
- if (NATURE(prog_name) == na_function && !has_return)
- #ifdef ERRNUM
- errmsgn(378, 32, node);
- #else
- errmsg("Missing RETURN statement in function body", "6.5", node);
- #endif
-
- check_incomplete_decls(prog_name, node);
- }
-
- Node new_not_equals(Symbol neq, Symbol eq) /*;new_not_equals*/
- {
- /* Build the tree for the body of an implicitly defined inequality op.
- * This is a prime candidate for on-line expansion later on.
- */
-
- Node node, id_node, arg1, arg2, a1, a2;
- Node call_node, not_node, ret_node, stat_node;
- Tuple sig, tup;
-
- node = node_new(as_subprogram_tr);
- sig = SIGNATURE(neq);
- arg1 = (Node) sig[1];
- arg2 = (Node) sig[2];
- a1 = (Node) new_name_node((Symbol) arg1);
- a2 = (Node) new_name_node((Symbol) arg2);
- tup = tup_new(2);
- tup[1] = (char *) a1;
- tup[2] = (char *) a2;
- call_node = new_call_node(eq, tup, symbol_boolean);
- not_node = new_unop_node(symbol_not, call_node, symbol_boolean);
- id_node = new_name_node(neq);
- ret_node = node_new(as_return);
- N_AST1(ret_node) = not_node; /* return not(arg1 = arg2)*/
- N_AST2(ret_node) = id_node;
- N_AST3(ret_node) = new_number_node(0); /* from top level */
- /*
- * Note that stat_node is N_AST1 so is because the node is as_subprogram_tr
- * which has the stat_node is N_AST1 instead of N_AST3 as it is for
- * as_subprogram.
- */
- stat_node = new_statements_node(tup_new1((char *) ret_node));
- N_AST1(node) = stat_node;
- N_AST2(node) = OPT_NODE;
- N_UNQ(node) = neq; /* ignore formals, etc .*/
- N_AST4(node) = OPT_NODE;
-
- return node;
- }
-
- Tuple process_formals(Symbol scope, Tuple form_list,int newi)
- /*;process_formals*/
- {
- /* This is called to process formal parameters of a procedure spec. or
- * entry spec.
- * The flag -newi- indicates whether this is the first time the object is
- * seen. For an entry or subprogram declaration, newi is true; for an
- * accept statement it is false. For a subprogram body it depends on
- * whether a separate specification was provided.
- */
-
- Tuple new_form_list, t, tup;
- int in_out, nat;
- Node opt_init;
- Symbol type_mark, form_name, f_nam;
- char *form_id;
- int i;
- Fortup ft1, ft2;
- char *id;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : process_formals");
-
- new_form_list = tup_new(0);
-
- /* Initialize -declared- map for new scope. */
-
- if (DECLARED(scope) == (Declaredmap)0)
- DECLARED(scope) = dcl_new(0);
- newscope(scope);
- nat = NATURE(scope);
- NATURE(scope) = na_void;
- FORTUP(t = (Tuple), form_list, ft1);
- form_id = t[1];
- in_out = (int) t[2];
- type_mark = (Symbol)t[3];
- opt_init = (Node) t[4];
-
- form_name = find_new(form_id);
- /* formals parameters cannot have an incomplete type. They can
- * have an incomplete private type however.
- */
- if (TYPE_OF(type_mark) == symbol_incomplete) {
- #ifdef ERRNUM
- id_errmsgn(379, type_mark, 5, current_node);
- #else
- errmsg_id("Invalid use of incomplete type %", type_mark,
- "3.8.1", current_node);
- #endif
- }
- TYPE_OF(form_name) = type_mark;
- default_expr(form_name) = (Tuple) opt_init;
- if (opt_init != OPT_NODE) {
- adasem(opt_init);
- normalize(type_mark, opt_init);
- }
- ORIG_NAME(form_name) = form_id;
-
- if (opt_init != OPT_NODE && newi && in_out != na_in) {
- #ifdef ERRNUM
- errmsgn(380, 381, current_node);
- #else
- errmsg("default initialization only allowed for IN parameters",
- "6.1", current_node);
- #endif
- opt_init = OPT_NODE;
- }
-
- /* Assignable parameters must not appear in functions.*/
- if ( in_out != na_in && (nat==na_function || nat==na_function_spec )) {
- #ifdef ERRNUM
- str_errmsgn(382, nature_str(in_out), 32, current_node);
- #else
- errmsg_str("functions cannot have % parameters ",
- nature_str(in_out), "6.5", current_node);
- #endif
- }
-
- TO_XREF(form_name);
- new_form_list = tup_with(new_form_list, (char *) form_name);
- ENDFORTUP(ft1);
- FORTUPI(t = (Tuple), form_list, i, ft1);
- /* at end of formal part, set mode of formal parameters */
- form_id = t[1];
- in_out = (int) t[2];
- form_name = (Symbol) new_form_list[i];
- NATURE(form_name) = in_out;
- ENDFORTUP(ft1);
-
- NATURE(scope) = nat;
- popscope();
- if (newi)
- return new_form_list;
- else { /* Verify that redeclaration matches. */
- FORTUPI(tup = (Tuple), form_list, i, ft2);
- id= tup[1];
- in_out = (int) tup[2];
- type_mark = (Symbol) tup[3];
- opt_init = (Node) tup[4];
- f_nam = (Symbol) (SIGNATURE(scope))[i];
- if (
- #ifdef TBSN
- -- skip this failed since original_name null even though had right
- symbol ds 1 aug
- strcmp(id, original_name(f_nam)) != 0 ||
- #endif
- in_out != NATURE(f_nam) || type_mark != TYPE_OF(f_nam) ) {
- /* missing conformance on init. */
- #ifdef ERRNUM
- errmsgn(383, 205, current_node);
- #else
- errmsg("Declaration does not match previous specification",
- "6.3.1", current_node);
- #endif
- }
- ENDFORTUP(ft2);
- return SIGNATURE(scope);
- }
- }
-
- static Tuple derived_formals(Symbol scope, Tuple form_list) /*;derived_formals*/
- {
- /* build list of formals for derived subprograms.
- * No semantic checks necessary
- */
-
- Tuple new_form_list, t;
- Symbol form_name, type_mark;
- char *form_id;
- int in_out;
- Node opt_init;
- Fortup ft1;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : derived_formals");
-
- new_form_list = tup_new(0);
-
- /* Initialize -declared- map for new scope. */
- DECLARED(scope) = dcl_new(0);
-
- newscope(scope);
-
- FORTUP(t = (Tuple), form_list, ft1);
- form_id = t[1];
- in_out = (int) t[2];
- type_mark = (Symbol)t[3];
- opt_init = (Node) t[4];
-
- form_name = find_new(form_id);
-
- NATURE(form_name) = in_out;
- TYPE_OF(form_name) = type_mark;
- default_expr(form_name) = (Tuple) opt_init;
- ORIG_NAME(form_name) = form_id;
-
- new_form_list = tup_with(new_form_list, (char *)form_name);
- ENDFORTUP(ft1);
- popscope();
-
- return(new_form_list);
- }
-
- void reprocess_formals(Symbol name, Node formals_node) /*;reprocess_formals */
- {
- /* check conformance of subprogram specifications given in spec and body.*/
-
- Node old_formals_node, old_node, new_node, old_id_list, type_node,
- init_node;
- Symbol formal, type_mark;
- Tuple old_list, new_list;
- char *id;
- int i;
-
- old_formals_node = (Node) formal_decl_tree(name);
- if (!conform(formals_node, old_formals_node)) {
- conformance_error(formals_node);
- return;
- }
-
- old_list = N_LIST(old_formals_node);
- new_list = N_LIST(formals_node);
- for (i = 1; i <= tup_size(old_list); i++) {
- old_node = (Node) old_list[i];
- new_node = (Node) new_list[i];
- old_id_list = N_AST1(old_node);
- type_node = N_AST3(new_node);
- type_mark = find_type(type_node);
- init_node = N_AST4(new_node);
- id = N_VAL((Node)N_LIST(old_id_list)[1]);
- formal = dcl_get(DECLARED(name), id);
- if (type_mark != TYPE_OF(formal)) {
- conformance_error(type_node);
- return;
- }
- if (init_node != OPT_NODE) {
- adasem(init_node);
- normalize(type_mark, init_node);
- }
- if (!same_expn(init_node, (Node)default_expr(formal))) {
- conformance_error(init_node);
- return;
- }
- }
- }
-
- void normalize(Symbol context_type, Node expn) /*;normalize*/
- {
- /* This procedure performs type resolution (as in check_type), without
- * constant folding.
- */
-
- Set types, otypes;
- Symbol t, old_context;
- Forset fs1;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : normalize");
-
- N_TYPE(expn) = symbol_any; /*By default.*/
- fold_context = FALSE; /* to inhibit constant folding elsewhere.*/
- noop_error = FALSE;
-
- resolve1(expn); /* Bottom-up pass.*/
-
- if (noop_error) {
- noop_error = FALSE; /* error emitted already*/
- return;
- }
-
- types = N_PTYPES(expn);
- old_context = context_type;
- if (in_type_classes(context_type)) {
- /* Keep only those that belong to this class.*/
- otypes = set_copy(types);
- types = set_new(0);
- FORSET(t = (Symbol), otypes, fs1);
- if (compatible_types(t, context_type))
- types = set_with(types, (char *) t);
- ENDFORSET(fs1);
- set_free(otypes);
-
- if (set_size(types) > 1) {
- /* May be overloaded operator: user_defined one hides predefined.*/
- /* types -:= univ_types */
- otypes = set_copy(types);
- types = set_new(0);
- FORSET(t = (Symbol), otypes, fs1);
- if (t != symbol_universal_integer && t != symbol_universal_real)
- types = set_with(types, (char *)t);
- ENDFORSET(fs1);
- set_free(otypes);
- }
-
- if (set_size(types) == 1) {
- context_type = (Symbol) set_arb (types );
- set_free(types);
- }
- else {
- type_error(set_new1((char *) symbol_any), context_type,
- set_size(types), expn);
- N_TYPE(expn) = symbol_any;
- set_free(types);
- fold_context = TRUE;
- return;
- }
- }
- resolve2(expn, context_type);
- fold_context = TRUE;
-
- if (noop_error) {
- noop_error = FALSE; /* error emitted already*/
- return;
- }
- /* Now emit a constraint qualification if needed.*/
- if (! in_type_classes(old_context) ) {
- apply_constraint(expn, context_type);
- }
- }
-
- int conform(Node exp1, Node exp2) /*;conform*/
- {
- /* Verify that two trees corresponding to two expressions are conformant,
- * according to 6.2.1. This procedure is called after ascertaining that
- * the trees denote the same entities. We now verify that their lexical
- * structure is conformant.
- */
-
- Tuple l1, l2;
- Node sel_node, pfx1, pfx2, sel1, sel2;
- int i, nk;
- char * id1;
-
- switch (N_KIND(exp1)) {
- case (as_simple_name):
- if (N_KIND(exp2) == as_simple_name)
- return streq(N_VAL(exp1), N_VAL(exp2));
- else if (N_KIND(exp2) == as_selector) {
- sel_node = N_AST2(exp2);
- id1 = N_VAL(exp1);
- return !in_op_designators(id1) && streq(id1, N_VAL(sel_node));
- }
- else if (N_KIND(exp2) == as_qual_range) {
- /* possible if first occurrence had private type.*/
- return conform(exp1, N_AST1(exp2));
- }
- else
- return FALSE;
- case (as_mode):
- return(N_VAL(exp1) == N_VAL(exp2)); /* mode is integer in C version */
- case (as_int_literal):
- return (N_KIND(exp2) == as_int_literal
- && const_eq(adaval(symbol_universal_integer, N_VAL(exp1)),
- adaval(symbol_universal_integer, N_VAL(exp2)) ));
- case (as_real_literal):
- return (N_KIND(exp2) == as_real_literal
- && const_eq(adaval(symbol_universal_real, N_VAL(exp1)),
- adaval(symbol_universal_real, N_VAL(exp2)) ) );
- case (as_string_literal):
- return(N_KIND(exp2) == as_string_literal
- && streq(N_VAL(exp1), N_VAL(exp2)));
- case (as_selector):
- pfx1 = N_AST1(exp1);
- sel1 = N_AST2(exp1);
- if (N_KIND(exp2) == as_simple_name )
- return (conform(exp2, exp1));
- else if (N_KIND(exp2) == as_selector ) {
- pfx2 = N_AST1(exp2);
- sel2 = N_AST2(exp2);
- return (conform(pfx1, pfx2) && streq(N_VAL(sel1), N_VAL(sel2)));
- }
- else
- return FALSE;
- break;
- default:
- if (N_KIND(exp1) != N_KIND(exp2) )
- return FALSE;
- else {
- /* if is_tuple(a1 := N_AST(exp1)) then
- * (for i in [1..#a1])
- * if not conform(a1(i), a2(i)) then return FALSE; end;
- * end for;
- */
- nk = N_KIND(exp1);
- if (N_AST1_DEFINED(nk) && N_AST1(exp1) != (Node)0) {
- if (!conform(N_AST1(exp1), N_AST1(exp2)))
- return FALSE;
- if (N_AST2_DEFINED(nk) && N_AST2(exp1) != (Node)0) {
- if (!conform(N_AST2(exp1), N_AST2(exp2)))
- return FALSE;
- if (N_AST3_DEFINED(nk) && N_AST3(exp1) != (Node)0) {
- if (!conform(N_AST3(exp1), N_AST3(exp2)))
- return FALSE;
- if (N_AST4_DEFINED(nk) &&N_AST4(exp1) != (Node)0) {
- if (!conform(N_AST4(exp1), N_AST4(exp2)))
- return FALSE;
- }
- }
- }
- }
- /* if is_tuple(l1 := N_LIST(exp1)) then
- * if #l1 != #(l2 := N_LIST(exp2) ? [])) then
- * return FALSE;
- * else
- * (for i in [1..#l1]))
- * if not conform(l1(i), l2(i)) then
- * return FALSE;
- * end if;
- * end if;
- * end if;
- */
- if (N_LIST_DEFINED(nk))
- l1 = N_LIST(exp1);
- else
- l1 = (Tuple) 0;
- if (l1 != (Tuple)0) {
- if (N_LIST_DEFINED(N_KIND(exp2)))
- l2 = N_LIST(exp2);
- else
- l2 = (Tuple) 0;
- if (l2 == (Tuple)0 || tup_size(l1) != tup_size(l2) )
- return FALSE;
- for (i = 1; i <= tup_size(l1); i++) {
- if (!conform((Node)l1[i], (Node)l2[i]))
- return FALSE;
- }
- }
- return TRUE; /* AST and LIST match. */
- }
- } /* end switch */
- }
-
- void call_statement(Node node) /*;call_statement*/
- {
- /* This procedure resolves call statements. Syntactically the node is
- * a name, possibly selected and indexed.
- * These statements can have one of the following meanings :
- * a) Procedure call.
- * b) entry call .
-
- * Procedure and entry calls are handled by first resolving the name, and
- * then type-checking the argument list. Complications arise for parame-
- * terless procedures and entries, and for parameterless entries in entry
- * entry families. In those cases, this procedure reformats the name by
- * appending an empty argument list.
- */
-
- Node c_node, arg_list;
- int nk;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : call_statement");
-
- c_node = N_AST1(node);
- if (N_KIND(c_node) == as_call_unresolved) {
- /* Rebuild call node: proc name, arg_list. */
- /* Next, do N_AST(node) = N_AST(c_node) */
- nk = N_KIND(node);
- if (N_AST1_DEFINED(nk)) N_AST1(node) = N_AST1(c_node);
- if (N_AST2_DEFINED(nk)) N_AST2(node) = N_AST2(c_node);
- if (N_AST3_DEFINED(nk)) N_AST3(node) = N_AST3(c_node);
- if (N_AST4_DEFINED(nk)) N_AST4(node) = N_AST4(c_node);
- }
- else if (N_KIND(c_node) == as_simple_name || N_KIND(c_node)==as_selector) {
- /* Parameterless procedure, */
- /* qualified name of entry. */
- arg_list = node_new(as_list); /* add empty argument list. */
- N_LIST(arg_list) = tup_new(0);
- N_AST1(node) = c_node;
- N_AST2(node) = arg_list;
- }
- else {
- #ifdef ERRNUM
- errmsgn(384, 3, node);
- #else
- errmsg("Invalid statement: not procedure or entry call", "5.1", node);
- #endif
- return;
- }
- proc_or_entry(node);
- }
-
- static void proc_or_entry(Node node) /*;proc_or_entry*/
- {
- /* Process procedure calls, entry calls, and calls to members of
- * entry families.
- * The statement : name(args);
- * can have 3 meanings :
- * a) It can be a procedure call.
- * b) It can be an entry call.
- * c) -name- can be the name of an entry family, and -args- an index
- * into that family. This is recognized by the fact that the type of
- * -name- is an array type.
- * In the first two cases, we must type-check and format the argument
- * list. In the last one, we must emit a parameterless entry call.
-
- * If the statement has the format : name(arg)(args);
-
- * then it can only be a call with parameters to an element of an
- * entry family.
- */
-
- Node obj_node, arg_list, a_node;
- Symbol obj_name, entr;
- Fortup ft1;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : proc_or_entry");
-
- obj_node = N_AST1(node);
- arg_list = N_AST2(node);
-
- adasem(obj_node);
- /* Perform name resolution on argument list.*/
- FORTUP(a_node = (Node), N_LIST(arg_list), ft1);
- adasem(a_node);
- ENDFORTUP(ft1);
-
- if (N_KIND(obj_node) == as_simple_name || N_KIND(obj_node) == as_selector) {
- find_old(obj_node);
- obj_name = N_UNQ(obj_node);
-
- /* Probably indicated in a different way */
- if (N_KIND(obj_node) != as_simple_name) {
- entry_call(node);
- }
- else if (obj_name != (Symbol)0 && NATURE(obj_name) == na_entry_family)
- /* entry family called within task body, without qualified name.*/
- entry_call(node);
- else if (N_OVERLOADED(obj_node)) {
- check_type(symbol_none, node);
-
- entr = N_UNQ(obj_node);
- if (entr != (Symbol)0 && NATURE(entr) == na_entry) {
- Symbol task_name;
- task_name = SCOPE_OF(entr);
- if (is_task_type(task_name))
- task_name = dcl_get(DECLARED(task_name), "current_task");
- N_KIND(obj_node) = as_entry_name;
- N_AST1(obj_node) = new_name_node(task_name);
- N_AST2(obj_node) = new_name_node(entr);
- N_AST3(obj_node) = OPT_NODE;
- }
- if (N_KIND(node) != as_call && N_KIND(node) != as_ecall) {
- #ifdef ERRNUM
- errmsgn(385, 386, node);
- #else
- errmsg("Invalid procedure or entry call", "6.5, 9.5", node);
- #endif
- }
-
- }
- else {
- /* If the name was undeclared, an error message was emitted
- * already. We can detect this case by the fact that the identifier
- * has type -any-.
- */
- if (TYPE_OF(obj_name) != symbol_any ) {
- #ifdef ERRNUM
- errmsgn(387, 3, node);
- #else
- errmsg("Invalid statement", "5.1", node);
- #endif
- }
- else {
- /* Make up a dummy symbol table entry, so that subsequent uses
- * of it have a chance of looking plausible.
- */
- NATURE(obj_name) = na_procedure;
- {
- int i, n;
- Tuple tup;
- n = tup_size(N_LIST(arg_list));
- tup = tup_new(n);
- for (i = 1; i <= n; i++)
- tup[i] = (char *) symbol_any_id;
- SIGNATURE(obj_name) = tup;
- }
- TYPE_OF(obj_name) = symbol_none;
- OVERLOADS(obj_name) = set_new1((char *) obj_name);
- }
- }
- }
- else {
- /* Case of an entry family call with parameters. */
- find_old(obj_node);
- if (N_TYPE(obj_node) == symbol_any || N_KIND(obj_node) != as_index ) {
- #ifdef ERRNUM
- errmsgn(388, 321, node);
- #else
- errmsg("Invalid call", "9.5", node);
- #endif
- }
- else entry_call(node);
- }
- }
-
-
- Symbol chain_overloads(char *id, int new_nat, Symbol new_typ, Tuple new_sig,
- Symbol parent_subp, Node formals_node) /*;chain_overloads*/
- {
- /* Insert procedure, function, or enumeration literal into the current
- * symbol table. Because these names can be overloaded, each set of
- * overloaded names visible in the current scope is held in the
- * -overload- attribute of the corresponding identifier.
- * If there is no actual overload, the unique name is generated as for
- * any other identifier. Otherwise, successive overloads in the same
- * scope are given an additional arbitrary suffix to distinguish them
- * one from the other.
- * The overloaded name in inserted in the current scope.
- */
-
- int old_nat, n;
- Symbol new_name, seen, name;
- Set current_overload;
- Forset fs1;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : chain_overloads");
-
- new_name = sym_new(new_nat);
-
- seen = dcl_get(DECLARED(scope_name), id);
- if (seen== (Symbol)0) {
- /* First occurrence in this scope. Define therein, and make visible
- * if scope is visible part of package specification.
- */
- dcl_put_vis(DECLARED(scope_name), id, new_name,
- NATURE(scope_name) == na_package_spec);
- ORIG_NAME(new_name) = id;
- new_over_spec(new_name, new_nat, new_typ, new_sig,
- parent_subp, formals_node);
- }
- else {
- /* Name already appears in current scope. One of the following
- * may be the case :
- * a) It is a redeclaration, either because a non-overloaded
- * instance of that id exists, or because an object with the
- * same signature has already been declared : indicate error.
- * b) It is the body of a function or procedure, whose specs
- * have already been seen. Update the corresponding entry.
- * c) It is a new object. Generate a new name, and make entry
- * for it.
- * d) It is a redeclaration of a derived subprogram. in that case
- * the derived subprogram becomes inaccessible.
- * e) If it is a derived subprogram, and there is an explicit user
- * defined one already, the derived one is discarded.
- */
- if (!can_overload(seen)) {
- #ifdef ERRNUM
- str_errmsgn(389, id, 390, current_node);
- #else
- errmsg_str("Redeclaration of identifier %", id, "8.3, 8.4",
- current_node);
- #endif
- return seen;
- }
- else {
- current_overload = set_copy(OVERLOADS(seen));
- /* If the current scope is a private part, make sure the visible
- * declaration has been saved, before any modification of overloads
- * set.
- */
- if ((scope_name != symbol_standard0) &&
- (NATURE(scope_name) == na_private_part ||
- NATURE(scope_name) == na_package) &&
- private_decls_get((Private_declarations)
- private_decls(scope_name), seen) == (Symbol)0 ) {
- private_decls_put((Private_declarations)
- private_decls(scope_name), seen);
- }
- }
- FORSET(name = (Symbol), current_overload, fs1);
- if (same_sig_spec(name, new_sig)
- && same_type(TYPE_OF(name), new_typ) ) {
- /* A homograph of the current declaration exists in the
- * scope. This is permissible only if one or both are
- * implicit declarations of derived subprogram or prede-
- * fined operation. The latter do not appear in Ada/Ed,
- * and we only need to consider derived subprograms.
- */
- if (is_derived_subprogram(name) ) {
- /* An explicit declaration redefines an implicitly
- * derived subprogram. Make the later unreachable.
- */
- OVERLOADS(seen) = set_less(OVERLOADS(seen), (char *) name);
- /* next line incorrect: code gen. needs to know parent */
- /* ALIAS(name) = (Symbol) 0; */
- }
- else if (parent_subp != (Symbol)0
- && streq(id, ORIG_NAME(parent_subp) )) {
- /* New declaration is derived subprogram.*/
- new_name = named_atom(id);
- if (new_nat != na_literal) {
- /* A derived subprogram is hidden by any other homograph
- * but may itself be further derived. Insert in symbol
- * table as new entity, which is only retrievable when
- * iterating over declared map. A derived literal is
- * also hidden by other declarations, but still exists
- * as a literal of the type. It is inserted in symbol
- * table but not in declared.
- */
- dcl_put(DECLARED(scope_name), strjoin(id, newat_str()),
- new_name);
- }
- new_over_spec(new_name, new_nat, new_typ, new_sig,
- parent_subp, formals_node);
- ORIG_NAME(new_name) = id;
- return new_name;
- }
- else {
- n = NATURE(name);
- if ((n == na_procedure_spec
- && new_nat == na_procedure)
- || (n == na_function_spec && new_nat == na_function)) {
- /* Subprogram body whose spec was already seen.*/
- NATURE(name) = new_nat;
- /* Verify conformance of formal param declarations.*/
- reprocess_formals(name, formals_node);
- return name;
- }
- else {
- #ifdef ERRNUM
- str_errmsgn(391, id, 392, current_node);
- #else
- errmsg_str("invalid declaration of homograph %",
- id, "8.3(17)", current_node);
- #endif
- return name;
- }
- }
- }
- ENDFORSET(fs1);
- /* If we fall through, this is a new entity. Build its symbol table
- * entry, and add it to the overload set already seen.
- * As declared(scope)(id) is already defined, we enter the entity in
- * the declared map using an arbitrary string. The new entity will
- * always be retrieved through overload(seen).
- * The name of the subprogram becomes hidden until the end of the spec.
- * In particular, it cannot be used inside the formal part.
- */
- /* add identifier name to result of newat_str to create a unique
- * anonymous entity which will not conflict with names generated
- * by anonymous_type
- */
- new_name = named_atom(id);
- dcl_put_vis(DECLARED(scope_name), strjoin(id, newat_str()), new_name,
- NATURE(scope_name) == na_package_spec);
- old_nat = NATURE(seen);
- NATURE(seen) = na_void;
- new_over_spec(new_name, new_nat, new_typ, new_sig,
- parent_subp, formals_node);
- NATURE(seen) = old_nat;
- OVERLOADS(seen) = set_with(OVERLOADS(seen) , (char *) new_name);
- ORIG_NAME(new_name) = id;
- }
- return new_name;
- }
-
- int can_overload(Symbol name) /*;can_overload*/
- {
- int n;
- n = NATURE(name);
- return (n == na_procedure_spec || n == na_function_spec || n == na_op
- || n == na_function || n == na_procedure || n == na_entry
- || n == na_literal);
- }
-
- static void new_over_spec(Symbol name, int nat, Symbol typ, Tuple sig,
- Symbol parent_subp, Node formals_node) /*;new_over_spec*/
- {
- /* Place in symbol table maps the specification of a new overloadable
- * object .
- */
-
- Symbol arg_type;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : new_over_spec");
-
- /* Apply the special checks on redefinitions of equality.*/
-
- NATURE(name) = nat;
- TYPE_OF(name) = typ;
- SCOPE_OF(name) = scope_name;
- OVERLOADS(name) = set_new1((char *) name);
- if (nat == na_literal) SIGNATURE(name) = tup_new(0);
-
- /* If the subprograms have the same name but the signatures have different
- * types or the subprograms have differing types it is a derived subprogram
- * otherwise it is a renaming of a subprogram.
- */
- else if (parent_subp != (Symbol) 0 &&
- streq(ORIG_NAME(name), ORIG_NAME(parent_subp)) &&
- (!same_sig_spec(parent_subp, sig) ||
- TYPE_OF(name) != TYPE_OF(parent_subp)))
- SIGNATURE(name) = derived_formals(name, sig);
- else {
- SIGNATURE(name) = process_formals(name, sig, TRUE);
- formal_decl_tree(name) = (Symbol) formals_node;
- }
- if (streq(original_name(name) , "=")) {
- /* introduce the implicit "/=" as well.*/
- chain_overloads("/=", na_function, typ, sig, (Symbol)0, OPT_NODE);
- arg_type = TYPE_OF((Symbol)SIGNATURE(name)[1]);
- if (!is_limited_type(arg_type) && parent_subp == (Symbol)0) {
- /* an equality operator can only be defined on limited types
- * unless it is introduced by a renaming declaration or derivation
- */
- #ifdef ERRNUM
- errmsgn(393, 54, current_node);
- #else
- errmsg("= can only be defined for limited types", "6.7",
- current_node);
- #endif
- }
- }
- TO_XREF(name);
- }
-
- int same_signature(Symbol sub1, Symbol sub2) /*;same_signature*/
- {
- /* Compare the signatures of two subprograms to determine whether
- * they hide each other. Two signatures are considered identical if
- * they have the same length, and the formals match in name and type.
- */
-
- int i;
- Symbol type1, type2;
- Tuple old, newi;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : same_signature");
-
- old = SIGNATURE(sub1);
- newi = SIGNATURE(sub2);
- if (old == newi) return TRUE;
- #ifdef TBSN
- == how to translate is_tuple ?? ds 8 jun
- else if (! is_tuple(old) || ! is_tuple(newi) ) {
- return FALSE;
- }
- #endif
- else if (tup_size(old) != tup_size(newi)) return FALSE;
- else {
- for (i = 1; i <= tup_size(old); i++) {
- type1 = (Symbol) old[i];
- type2 = (Symbol) newi[i];
- if (! same_type(TYPE_OF(type1), TYPE_OF(type2)) ) return FALSE;
- }
- return TRUE;
- }
- }
-
- int same_sig_spec(Symbol subp, Tuple spec) /*;same_sig_spec*/
- {
- /* Compare the signature of a subprogram with the formals list of a
- * new subprogram specification.
- */
-
- Tuple sig;
- Tuple tup;
- int i;
- Symbol new_typ;
- Symbol sym;
-
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : same_sig_spec");
-
- sig = SIGNATURE(subp);
-
- if (tup_size(sig) != tup_size(spec)) return FALSE;
- else {
- for (i = 1; i <= tup_size(sig); i++) {
- tup = (Tuple) spec[i];
- new_typ = (Symbol)tup[3];
- sym = (Symbol)(sig[i]);
- if (!same_type(TYPE_OF(sym), new_typ)) return FALSE;
- }
- return TRUE;
- }
- }
-
- int same_type(Symbol type1, Symbol type2) /*;same_type*/
- {
- if (cdebug2 > 3) TO_ERRFILE("AT PROC : same_type");
-
- return (base_type(type1) == base_type(type2) );
- }
-